package cn.lingyangwl.agile.pay.pay.service;


import cn.lingyangwl.agile.pay.common.constants.Cs;
import cn.lingyangwl.agile.pay.common.service.*;
import cn.lingyangwl.agile.pay.pay.model.bo.IsvConfigContext;
import cn.lingyangwl.agile.pay.pay.model.bo.MchAppConfigContext;
import cn.lingyangwl.agile.pay.pay.model.bo.MchInfoConfigContext;
import cn.lingyangwl.agile.pay.pay.model.params.IsvParams;
import cn.lingyangwl.agile.pay.pay.model.params.NormalMchParams;
import cn.lingyangwl.agile.pay.constant.IfCodeEnum;
import cn.lingyangwl.agile.pay.model.entity.IsvInfo;
import cn.lingyangwl.agile.pay.model.entity.MchApp;
import cn.lingyangwl.agile.pay.model.entity.MchInfo;
import cn.lingyangwl.agile.pay.model.entity.PayInterfaceConfig;
import cn.lingyangwl.agile.pay.pay.factory.AbstractPayFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 商户/服务商 配置信息上下文服务
 *
 * @author shenguangyang
 */
@Slf4j
@Service
public class ConfigContextService {

    /**
     * <商户ID, 商户配置项>
     */
    private static final Map<String, MchInfoConfigContext> mchInfoConfigContextMap = new ConcurrentHashMap<>();

    /**
     * <应用ID, 商户配置上下文>
     */
    private static final Map<String, MchAppConfigContext> mchAppConfigContextMap = new ConcurrentHashMap<>();

    /**
     * <服务商号, 服务商配置上下文>
     */
    private static final Map<String, IsvConfigContext> isvConfigContextMap = new ConcurrentHashMap<>();

    @Resource
    private MchInfoService mchInfoService;
    @Resource
    private MchAppService mchAppService;
    @Resource
    private IsvInfoService isvInfoService;
    @Resource
    private PayInterfaceConfigService payInterfaceConfigService;


    /**
     * 获取 [商户配置信息]
     */
    public MchInfoConfigContext getMchInfoConfigContext(String mchNo) {

        MchInfoConfigContext mchInfoConfigContext = mchInfoConfigContextMap.get(mchNo);

        //无此数据， 需要初始化
        if (mchInfoConfigContext == null) {
            initMchInfoConfigContext(mchNo);
        }

        return mchInfoConfigContextMap.get(mchNo);
    }

    /**
     * 获取 [商户应用支付参数配置信息]
     */
    public MchAppConfigContext getMchAppConfigContext(String mchNo, String appId) {

        MchAppConfigContext mchAppConfigContext = mchAppConfigContextMap.get(appId);

        //无此数据， 需要初始化
        if (mchAppConfigContext == null) {
            initMchAppConfigContext(mchNo, appId);
        }

        return mchAppConfigContextMap.get(appId);
    }

    /**
     * 获取 [ISV支付参数配置信息]
     */
    public IsvConfigContext getIsvConfigContext(String isvNo) {

        IsvConfigContext isvConfigContext = isvConfigContextMap.get(isvNo);
        // 无此数据， 需要初始化
        if (isvConfigContext == null) {
            initIsvConfigContext(isvNo);
        }

        return isvConfigContextMap.get(isvNo);
    }


    /**
     * 初始化 [商户配置信息]
     */
    public synchronized void initMchInfoConfigContext(String mchNo) {

        if (!isCache()) { // 当前系统不进行缓存
            return;
        }

        //商户主体信息
        MchInfo mchInfo = mchInfoService.getById(mchNo);
        if (mchInfo == null) { // 查询不到商户主体， 可能已经删除
            MchInfoConfigContext mchInfoConfigContext = mchInfoConfigContextMap.get(mchNo);

            // 删除所有的商户应用
            if (mchInfoConfigContext != null) {
                mchInfoConfigContext.getAppMap().forEach((k, v) -> mchAppConfigContextMap.remove(k));
            }

            mchInfoConfigContextMap.remove(mchNo);
            return;
        }

        MchInfoConfigContext mchInfoConfigContext = new MchInfoConfigContext();

        // 设置商户信息
        mchInfoConfigContext.setMchNo(mchInfo.getMchNo());
        mchInfoConfigContext.setMchType(mchInfo.getType());
        mchInfoConfigContext.setMchInfo(mchInfo);
        mchAppService.list(MchApp.lqw().eq(MchApp::getMchNo, mchNo)).forEach(mchApp -> {
            //1. 更新商户内appId集合
            mchInfoConfigContext.putMchApp(mchApp);

            MchAppConfigContext mchAppConfigContext = mchAppConfigContextMap.get(mchApp.getId());
            if (mchAppConfigContext != null) {
                mchAppConfigContext.setMchApp(mchApp);
                mchAppConfigContext.setMchNo(mchInfo.getMchNo());
                mchAppConfigContext.setMchType(mchInfo.getType());
                mchAppConfigContext.setMchInfo(mchInfo);
            }
        });

        mchInfoConfigContextMap.put(mchNo, mchInfoConfigContext);
    }

    /**
     * 初始化 [商户应用支付参数配置信息]
     */
    public synchronized void initMchAppConfigContext(String mchNo, String appId) {
        if (!isCache()) { // 当前系统不进行缓存
            return;
        }

        // 获取商户的配置信息
        MchInfoConfigContext mchInfoConfigContext = getMchInfoConfigContext(mchNo);
        if (mchInfoConfigContext == null) { // 商户信息不存在
            return;
        }

        // 查询商户应用信息主体
        MchApp dbMchApp = mchAppService.getById(appId);

        // DB已经删除
        if (dbMchApp == null) {
            mchAppConfigContextMap.remove(appId);  //清除缓存信息
            mchInfoConfigContext.getAppMap().remove(appId); //清除主体信息中的appId
            return;
        }

        // 商户应用mchNo 与参数不匹配
        if (!dbMchApp.getMchNo().equals(mchNo)) {
            return;
        }

        // 更新商户信息主体中的商户应用
        mchInfoConfigContext.putMchApp(dbMchApp);

        //商户主体信息
        MchInfo mchInfo = mchInfoConfigContext.getMchInfo();
        MchAppConfigContext mchAppConfigContext = new MchAppConfigContext();

        // 设置商户信息
        mchAppConfigContext.setAppId(appId);
        mchAppConfigContext.setMchNo(mchInfo.getMchNo());
        mchAppConfigContext.setMchType(mchInfo.getType());
        mchAppConfigContext.setMchInfo(mchInfo);
        mchAppConfigContext.setMchApp(dbMchApp);

        // 查询商户的所有支持的参数配置
        List<PayInterfaceConfig> allConfigList = payInterfaceConfigService.list(PayInterfaceConfig.lqw()
                .select(PayInterfaceConfig::getIfCode, PayInterfaceConfig::getIfParams)
                .eq(PayInterfaceConfig::getStatus, Cs.YES)
                .eq(PayInterfaceConfig::getInfoType, Cs.INFO_TYPE_MCH_APP)
                .eq(PayInterfaceConfig::getInfoId, appId)
        );

        // 普通商户
        if (Objects.equals(mchInfo.getType(), Cs.MCH_TYPE_NORMAL)) {
            for (PayInterfaceConfig payInterfaceConfig : allConfigList) {
                IfCodeEnum ifCodeEnum = IfCodeEnum.ofByCode(payInterfaceConfig.getIfCode());
                mchAppConfigContext.getNormalMchParamsMap().put(
                        ifCodeEnum.getCode(),
                        AbstractPayFactory.getInstance(ifCodeEnum).buildNormalMchParams(payInterfaceConfig.getIfParams())
                );
            }

            // 放置pay client
            for (IfCodeEnum ifCodeEnum : IfCodeEnum.values()) {
                NormalMchParams normalMchParams = mchAppConfigContext.getNormalMchParamsByIfCode(ifCodeEnum);
                if (normalMchParams != null) {
                    mchAppConfigContext.addClientWrapper(ifCodeEnum, AbstractPayFactory.getInstance(ifCodeEnum).buildClientWrapper(normalMchParams));
                }
            }


        } else { //服务商模式商户
            for (PayInterfaceConfig payInterfaceConfig : allConfigList) {
                IfCodeEnum ifCode = IfCodeEnum.ofByCode(payInterfaceConfig.getIfCode());
                mchAppConfigContext.getIsvsubMchParamsMap().put(
                        ifCode.getCode(),
                        AbstractPayFactory.getInstance(ifCode).buildIsvsubMchParams(payInterfaceConfig.getIfParams())
                );
            }

            //放置 当前商户的 服务商信息
            mchAppConfigContext.setIsvConfigContext(getIsvConfigContext(mchInfo.getIsvNo()));

        }

        mchAppConfigContextMap.put(appId, mchAppConfigContext);
    }


    /**
     * 初始化 [ISV支付参数配置信息]
     */
    public synchronized void initIsvConfigContext(String isvNo) {

        if (!isCache()) { // 当前系统不进行缓存
            return;
        }

        //查询出所有商户的配置信息并更新
        List<String> mchNoList = new ArrayList<>();
        mchInfoService.list(MchInfo.lgw()
                .select(MchInfo::getMchNo).eq(MchInfo::getIsvNo, isvNo)).forEach(r -> mchNoList.add(r.getMchNo()));

        // 查询出所有 所属当前服务商的所有应用集合
        List<String> mchAppIdList = new ArrayList<>();
        if (!mchNoList.isEmpty()) {
            mchAppService.list(MchApp.lqw()
                    .select(MchApp::getId).in(MchApp::getMchNo, mchNoList)).forEach(r -> mchAppIdList.add(r.getId()));
        }

        IsvConfigContext isvConfigContext = new IsvConfigContext();
        IsvInfo isvInfo = isvInfoService.getById(isvNo);
        if (isvInfo == null) {

            for (String appId : mchAppIdList) {
                //将更新已存在缓存的商户配置信息 （每个商户下存储的为同一个 服务商配置的对象指针）
                MchAppConfigContext mchAppConfigContext = mchAppConfigContextMap.get(appId);
                if (mchAppConfigContext != null) {
                    mchAppConfigContext.setIsvConfigContext(null);
                }
            }

            isvConfigContextMap.remove(isvNo); // 服务商有商户不可删除， 此处不再更新商户下的配置信息
            return;
        }

        // 设置商户信息
        isvConfigContext.setIsvNo(isvInfo.getIsvNo());
        isvConfigContext.setIsvInfo(isvInfo);

        // 查询商户的所有支持的参数配置
        List<PayInterfaceConfig> allConfigList = payInterfaceConfigService.list(PayInterfaceConfig.lqw()
                .select(PayInterfaceConfig::getIfCode, PayInterfaceConfig::getIfParams)
                .eq(PayInterfaceConfig::getStatus, Cs.YES)
                .eq(PayInterfaceConfig::getInfoType, Cs.INFO_TYPE_ISV)
                .eq(PayInterfaceConfig::getInfoId, isvNo)
        );

        for (PayInterfaceConfig payInterfaceConfig : allConfigList) {
            IfCodeEnum ifCodeEnum = IfCodeEnum.ofByCode(payInterfaceConfig.getIfCode());
            isvConfigContext.getIsvParamsMap().put(
                    ifCodeEnum,
                    AbstractPayFactory.getInstance(ifCodeEnum).buildIsvParams(payInterfaceConfig.getIfParams())
            );
        }

        // client
        for (IfCodeEnum ifCodeEnum : IfCodeEnum.values()) {
            IsvParams isvParams = isvConfigContext.getIsvParamsByIfCode(ifCodeEnum);
            if (isvParams != null) {
                isvConfigContext.addClientWrapper(ifCodeEnum, AbstractPayFactory.getInstance(ifCodeEnum).buildClientWrapper(isvParams));
            }
        }

        isvConfigContextMap.put(isvNo, isvConfigContext);

        //查询出所有商户的配置信息并更新
        for (String appId : mchAppIdList) {
            //将更新已存在缓存的商户配置信息 （每个商户下存储的为同一个 服务商配置的对象指针）
            MchAppConfigContext mchAppConfigContext = mchAppConfigContextMap.get(appId);
            if (mchAppConfigContext != null) {
                mchAppConfigContext.setIsvConfigContext(isvConfigContext);
            }
        }
    }

    private boolean isCache() {
        return PaySysConfigService.IS_USE_CACHE;
    }

    /**
     * 移除应用缓存
     */
    public void cleanMchAppCache(String mchAppId) {
        mchAppConfigContextMap.remove(mchAppId);
    }
}
